#include<iostream>
#include<map>
using namespace std;
enum Color { RED, BLACK };
template<class K, class T>
struct BATreeNode{
	BATreeNode* _parent;
	BATreeNode* _right;
	BATreeNode* _left;
	pair<K,T> _kv;
	Color _col;
	BATreeNode(const pair<K,T>& kv)
		:_parent(nullptr)
		,_right(nullptr)
		,_left(nullptr)
		,_kv(kv)
		,_col(RED)
	{}
};
template<class K, class T>
class RBtree {
	typedef BATreeNode<K,T> Node;
public:
	
	bool insert(const pair<K, T>& kv)
	{
		Node* parent = _root;
		Node* cur = _root;
		if (_root == nullptr)
		{
			_root = new Node(kv);
			_root->_col = BLACK;
			return true;
		}
		while (cur)
		{
			
			if (cur->_kv.first > kv.first)
			{
				parent = cur;
				cur = cur->_left;
			}
			else if (cur->_kv.first < kv.first)
			{
				parent = cur;
				cur = cur->_right;
			}
			else
				return false;
		}
		cur = new Node(kv);
		if (parent->_kv.first > kv.first)
		{
			cur->_parent = parent;
			parent->_left = cur;
		}
		else if (parent->_kv.first < kv.first)
		{
			cur->_parent = parent;
			parent->_right = cur;
		}
		while (parent&&parent->_col!=BLACK)
		{
			Node* grandfather = parent->_parent;
			if (grandfather && grandfather->_left==parent)
			{
				Node* uncle = grandfather->_right;
				if (uncle && uncle->_col == RED)
				{
					parent->_col = BLACK;
					uncle->_col = BLACK;
					grandfather->_col = RED;
					cur = grandfather;
					parent = grandfather->_parent;
				}
				else if (uncle == nullptr&&cur==parent->_left)
				{
					reverseright(parent);
					parent->_col = BLACK;
					grandfather->_col = RED;

				}
				else if (uncle == nullptr && cur == parent->_right)
				{
					reverseleft(parent);
					reverseright(grandfather);
					grandfather->_col = RED;
					cur->_col = BLACK;
				}
				else if (uncle && uncle->_col == BLACK)
				{
					
					if (cur == parent->_right)
					{
						reverseleft(parent);
						swap(cur, parent);		
					}
					else
					{
						reverseright(grandfather);
						parent->_col = BLACK;
						grandfather->_col = RED;
					}
				}
			}
			else if (grandfather && grandfather->_right == parent)
			{
				Node* uncle = grandfather->_left;
				if (uncle&& uncle->_col == RED)
				{
					parent->_col = uncle->_col = BLACK;
					grandfather->_col = RED;
					cur = grandfather;
					parent = grandfather->_parent;
				}
				if (uncle && uncle->_col == BLACK)
				{
					if (cur == parent->_left)
					{
						reverseright(parent);
						swap(parent, cur);
					}
					else
					{
						reverseleft(grandfather);
						grandfather->_col = RED;
						parent->_col = BLACK;
					}
				}
			}
		}
		_root->_col = BLACK;
		return true;
	}

	void reverseright(Node* parent)
	{
		Node* pre = parent->_parent;
		Node* subleft = parent->_left;
		Node* subleftright = subleft->_right;
		parent->_left = subleft->_right;
		subleft->_right = parent;
		subleft->_parent = pre;
		parent->_parent = subleft;
		if (subleftright)
			subleftright->_parent = parent;
		if (pre == nullptr)
		{
			_root = subleft;
			subleft->_parent = nullptr;
		}
		else
		{
			if (pre->_right == parent)
				pre->_right = subleft;
			else
				pre->_left = subleft;
		}
		
	}
	void reverseleft(Node* parent)
	{
		Node* subright = parent->_right;
		Node* pre = parent->_parent;
		Node* subrightleft = subright->_left;
		parent->_right = subrightleft;
		if (subrightleft)
			subrightleft->_parent = parent;
		subright->_left = parent;
		parent->_parent = subright;
		subright->_parent = pre;
		if (pre == nullptr)
		{
			_root = subright;
			subright->_parent = nullptr;
		}
		else
		{
			if (pre->_left == parent)
				pre->_left = subright;
			else
				pre->_right = subright;
		}
	}
	void find(Node* p)
	{
		if (p == nullptr)
		{
			return;
		}
		find(p->_left);
		cout << p->_kv.first << " " << p->_kv.first << endl;
		find(p->_right);
	}
	void _find()
	{
		find(_root);
	}

private:
	Node* _root = nullptr;
};
void tree()
{
	/*int a[] = { 16, 3, 7, 11, 9, 26, 18, 14, 15 };*/
	int a[] = { 4, 2, 6, 1, 3, 5, 15, 7, 16, 14 };
	RBtree<int, int> c;
	for (auto e : a)
	{
		c.insert(make_pair(e, e));
	}
	c._find();
	/*cout << c._isbalance() << endl;*/
}
int main()
{
	tree();

	return 0;
}